package client.gui;

import java.awt.Button;
import java.awt.GridLayout;
import java.awt.TextField;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.BufferedInputStream;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ConnectException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

import shared.messages.IncorrectNameMessage;
import shared.messages.NameOkMessage;
import shared.util.Config;
import client.lobby.WaitingLobby;

/**
 * The Class EnterLobbyGui
 *  - allows the player to enter the name he/she wants to use in the game,
 *   connects to the server.
 */
public class EnterLobbyGui extends JPanel{
	
	/** The universal version identifier. */
	private static final long serialVersionUID = -377830958247139851L;
	
	/** The Jframe to which the enterlobbygui panel is added to. */
	JFrame frame;
	
	/** The name of the player. */
	String name;
	
	/** Traffic in. */
	private ObjectInputStream netIn;
	
	/** Traffic out. */
	private PrintWriter netOut;
	
	/** The socket used for establishing a connection with the server. */
	private Socket socket;
	
	/** The ip address of the server. */
	private String serverName;
	
	/** The port for establishing a connection with the server. */
	private int port = 8888;
	
	/** The name box used to get the players name. */
	TextField nameBox;
	
	/** The configuration object. */
	Config conf;
	
	/** True if the client should receive an incorrectname error. */
	boolean incorrectName = false;
	
	/**
	 * Instantiates a new enter lobby gui.
	 */
	public EnterLobbyGui() {
		run();
	}
	/**
	 * Run.
	 * - create the gui and wait for input
	 */
	public void run() {
		frame = new JFrame("Hello");
		frame.setSize(200, 100);
		frame.setResizable(false);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setVisible(true);
		JLabel lbl = new JLabel("Enter your name: ", JLabel.CENTER);
		nameBox = new TextField();
		this.setLayout(new GridLayout(3, 1));
		Button Submit = new Button("Submit");
		frame.add(this);
		this.add(lbl);
		this.add(nameBox);
		//add a mouselistener
		Submit.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseReleased(MouseEvent e) {
				submit();
				
			}
		});
		this.add(Submit);
	}

	/**
	 * Submit
	 *  - gets the players name and disposes of the jframe.
	 */
	protected void submit() {
		name = nameBox.getText();
		try {
			//get the configuration file
			conf = new Config("config.xml");
		} catch (FileNotFoundException e) {
			new ErrorMessageGui("Config file not found.");
		}
		//get the ip and port needed for a connection
		serverName = conf.getIp();
		port = conf.getPort();
		//connect
		if(connect()){
			dispose();
			@SuppressWarnings("unused")
			WaitingLobby lobby = new WaitingLobby(name, netIn, netOut, conf);
		}else{
			dispose();
			if(incorrectName){
				new EnterLobbyGui();
				new IncorrectNameGui();
			}
		}
	}

	/**
	 * Dispose - disposes of this frame.
	 */
	public void dispose() {
		frame.dispose();
	}

	/**
	 * Connect - tries to connect to the server.
	 *
	 * @return true, if successful
	 */
	public boolean connect() {
		try {
			InetAddress serverAddr = InetAddress.getByName(serverName);
			try {
				socket = new Socket(serverAddr, port);
				try {
					//traffic in and out
					netOut = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
							socket.getOutputStream())), true);
					netIn = new ObjectInputStream(new BufferedInputStream(socket.getInputStream()));
					//send the server your chosen name
					netOut.println(name);
					Object in = null;
					try {
						in = netIn.readObject();
					} catch (ClassNotFoundException e) {
						new ErrorMessageGui("Object class not found");
					}
					//if the player provided an incorrect name
					if(in instanceof IncorrectNameMessage){
						incorrectName = true;
						socket.close();
						return false;
					}else if(in instanceof NameOkMessage){
						return true;
					}
					return false;
				} finally {
					
				}

			} catch (ConnectException e) {
				new ErrorMessageGui("Cannot connect to server");
				this.dispose();
				return false;

			} catch (IOException e) {
				new ErrorMessageGui("Input error");
				this.dispose();
				return false;
			}

		} catch (UnknownHostException e) {
			new ErrorMessageGui("Unknown server: " + e.getMessage());
			this.dispose();
			return false;
		}
	}
}
